home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
general
/
raytrace
/
rayshade
/
graphtal.lzh
/
Graphtal.Amiga
/
WireDevice.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-17
|
5KB
|
223 lines
/*
* WireDevice.C - wire frame device driver.
*
* Copyright (C) 1992, Christoph Streit (streit@iam.unibe.ch)
* University of Berne, Switzerland
* All rights reserved.
*
* This software may be freely copied, modified, and redistributed
* provided that this copyright notice is preserved on all copies.
*
* You may not distribute this software, in whole or in part, as part of
* any commercial product without the express consent of the authors.
*
* There is no warranty or other guarantee of fitness of this software
* for any purpose. It is provided solely "as is".
*
*/
#include "WireDevice.h"
#include "Polygon.h"
#include "Sphere.h"
static const int defaultConeResolution = 3;
static const int defaultSphereResolution = 4;
//___________________________________________________________ WireDevice
WireDevice::WireDevice(BaseWindow* window, Options* options)
: DeviceDriver(options), w(window), polys(NULL)
{
coneResolution = (theOptions->coneResolution <= 0)
? defaultConeResolution
: theOptions->coneResolution;
sphereResolution = (theOptions->sphereResolution <= 0)
? defaultSphereResolution
: theOptions->sphereResolution;
/*
* Make up table for cone generation.
*/
sintable = new real[coneResolution];
costable = new real[coneResolution];
for (register int i=0; i<coneResolution; i++) {
real alpha = (2*M_PI*i)/coneResolution;
sintable[i] = sin(alpha);
costable[i] = cos(alpha);
}
top = new Vector[coneResolution];
bottom = new Vector[coneResolution];
/*
* Generate unit sphere.
*/
unitSphere = Sphere::tesselation(Vector(0,0,0), 1, sphereResolution);
}
WireDevice::~WireDevice()
{
delete [] sintable;
delete [] costable;
delete [] top;
delete [] bottom;
delete w;
for (register long i=0; i<unitSphere->count(); i++)
delete unitSphere->item(i);
delete unitSphere;
StringTable_Iterator macroItr(macroNames);
while(macroItr.more()){
PolygonList* polys = (PolygonList*)macroItr.cur_value();
for (i = 0; i<polys->count(); i++)
delete polys->item(i);
delete polys;
macroItr.next();
}
}
void WireDevice::begin()
{
if (!theOptions->autoscale) {
w->disableBuffering();
w->setView(theOptions->eye, theOptions->lookat, theOptions->up,
theOptions->fov);
}
w->open(theOptions->resX, theOptions->resY, "L-System " + LSystemName);
if (theOptions->autoscale)
w->writeText("Please wait ...",
theOptions->resX/2-40, theOptions->resY/2-5);
}
void WireDevice::end(const BoundingBox& b)
{
char key;
if (theOptions->verbose)
cerr << "primitives: "<< primitives << '\n';
if (theOptions->autoscale) {
w->setView(b, theOptions->up, theOptions->fov);
w->clear();
}
w->flush();
do {
key = w->waitForKey();
} while(key != 'q' && key != 'Q');
w->close();
}
void WireDevice::cylinder(const Vector& p1, const Vector& p2, real r)
{
cone(p1, r, p2, r);
}
void WireDevice::cone(const Vector& p1, real r1, const Vector& p2, real r2)
{
Vector axis = p2-p1;
/*
* Degenerated cone?
*/
if (axis.normalize() == 0)
return;
Vector u, v;
/*
* Calculate 2 vectors normal to cone axis and to each other.
*/
u[0] = -axis[1]; u[1] = axis[0]; u[2] = 0;
if (u.normalize() == 0) {
u[0] = axis[2]; u[1] = 0; u[2] = -axis[0];
u.normalize();
}
v = axis*u;
Vector d;
for (register int i=0; i<coneResolution; i++) {
d = costable[i]*u + sintable[i]*v;
*(bottom+i) = p1 + d*r1;
*(top+i) = p2 + d*r2;
}
for (i=0; i<coneResolution; i++) {
Polygon* p = new Polygon(*(bottom+i), *(top+i),
*(top+((i+1)%coneResolution)),
*(bottom+((i+1)%coneResolution)));
if (definingMacro)
polys->append(p);
else {
primitives++;
w->polygon(p);
}
}
}
void WireDevice::polygon(Polygon* p)
{
if (definingMacro)
polys->append(p);
else {
primitives++;
w->polygon(p);
}
}
void WireDevice::sphere(const Vector& pos, real r)
{
/*
* Transform the unit sphere to radius r and position pos.
*/
for (register long i=0; i<unitSphere->count(); i++) {
Polygon* p = unitSphere->item(i);
Polygon* transformedPoly = new Polygon(p->numVertices());
for (register long j=0; j<p->numVertices(); j++)
transformedPoly->addVertex(p->vertex(j)*r+pos);
if (definingMacro)
polys->append(transformedPoly);
else {
primitives++;
w->polygon(transformedPoly);
}
}
}
void WireDevice::beginMacro(const rcString& macroName)
{
definingMacro = 1;
currentMacroName = macroName;
polys = new PolygonList(100);
}
void WireDevice::endMacro()
{
definingMacro = 0;
macroNames.find_and_replace(currentMacroName, polys);
polys = NULL;
}
void WireDevice::executeMacro(const rcString& macroName,
const TransMatrix& tmat)
{
anyPtr argument;
if (!macroNames.lookup(macroName, argument))
Error(ERR_PANIC, "WireDevice::executeMacro: macro "
+ macroName + " does not exist");
PolygonList* polyList = (PolygonList*) argument;
for (register long i=0; i<polyList->count(); i++) {
Polygon* p = new Polygon(*polyList->item(i));
p->transform(tmat);
if (definingMacro)
polys->append(p);
else {
primitives++;
w->polygon(p);
}
}
}